#include "includes.h"
#include "stm32f4xx_i2c.h"
#include "sys.h"
#include "tools.h"
#include "port/datatype.h"
#include "port/sys_config.h"
#include "onps_errors.h"
#include "port/os_datatype.h"
#include "onps_utils.h"
#include "netif/netif.h"
#include "netif/route.h"


#define SYMBOL_GLOBALS
#include "at24c02.h"
#undef SYMBOL_GLOBALS

#if NETTOOLS_TELNETSRV  
void E2Init(void)
{
	GPIO_InitTypeDef stGPIO; 
  I2C_InitTypeDef  stI2C;
  
	//* 使能时钟
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 
	
  //* 初始设置I2C各功能引脚
  GPIO_PinAFConfig(AT24C_PIN_PORT, AT24C_I2C_SCL_PINSRC, GPIO_AF_I2C1);    
	GPIO_PinAFConfig(AT24C_PIN_PORT, AT24C_I2C_SDA_PINSRC, GPIO_AF_I2C1);  
	stGPIO.GPIO_Pin   = AT24C_I2C_SCL_PIN | AT24C_I2C_SDA_PIN;
	stGPIO.GPIO_Mode  = GPIO_Mode_AF;
	stGPIO.GPIO_Speed = GPIO_Speed_50MHz; 
  stGPIO.GPIO_OType = GPIO_OType_OD;
	stGPIO.GPIO_PuPd  = GPIO_PuPd_UP;
	GPIO_Init(AT24C_PIN_PORT, &stGPIO); 
  
  //* 开启407的I2C
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); 
  stI2C.I2C_Mode                = I2C_Mode_I2C;   
	stI2C.I2C_DutyCycle           = I2C_DutyCycle_2;  
	stI2C.I2C_OwnAddress1         = 0x0A;  
	stI2C.I2C_Ack                 = I2C_Ack_Enable;   
	stI2C.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  
	stI2C.I2C_ClockSpeed          = 1000000;  /** Enable the I2C peripheral */  
	I2C_Init(AT24C_I2C_PORT, &stI2C);
	I2C_Cmd(AT24C_I2C_PORT, ENABLE);
}

static void I2CDelay(USHORT usCnt)
{
  while(usCnt--); 
}

//* 等待获取I2C总线控制权 判断忙状态
static void I2CAckPolling(void)
{
  __IO USHORT usSR1;
  do
  {    
    I2C_GenerateSTART(AT24C_I2C_PORT, ENABLE); //* 起始位      
    usSR1 = I2C_ReadRegister(AT24C_I2C_PORT, I2C_Register_SR1); //* 读SR1
    
    //* 器件地址(写)
  #ifdef AT24C01
    I2C_Send7bitAddress(AT24C_I2C_PORT, 0, I2C_Direction_Transmitter);
  #else
    I2C_Send7bitAddress(AT24C_I2C_PORT, AT24C_I2C_ADDR, I2C_Direction_Transmitter);
  #endif

  }while(!(I2C_ReadRegister(AT24C_I2C_PORT, I2C_Register_SR1) & 0x0002));
  
  I2C_ClearFlag(AT24C_I2C_PORT, I2C_FLAG_AF);    
  I2C_GenerateSTOP(AT24C_I2C_PORT, ENABLE);  //* 停止位
}

void E2Read(UCHAR ubAddr, UCHAR *pubReadBuf, USHORT usBytesToRead)
{ 
  //* 等待I2C就绪
  while(I2C_GetFlagStatus(AT24C_I2C_PORT, I2C_FLAG_BUSY)); 
  
  //* 允许单字节应答模式
	I2C_AcknowledgeConfig(AT24C_I2C_PORT, ENABLE); 
  
  //* 发送起始位
  I2C_GenerateSTART(AT24C_I2C_PORT, ENABLE); 
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_MODE_SELECT)); //* AT24C为从机，MCU为主机
  
#ifdef AT24C01
  //* 发送器件地址(读)24C01
	I2C_Send7bitAddress(AT24C_I2C_PORT, ubAddr << 1, I2C_Direction_Receiver);
	while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
#else
  //* 发送器件地址(写)
  I2C_Send7bitAddress(AT24C_I2C_PORT,  AT24C_I2C_ADDR, I2C_Direction_Transmitter); 
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 
  
  //* 发送地址
	I2C_SendData(AT24C_I2C_PORT, ubAddr); 
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); 
  
  //* 起始位
	I2C_GenerateSTART(AT24C_I2C_PORT, ENABLE);
	while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_MODE_SELECT));
	
	//* 器件读
	I2C_Send7bitAddress(AT24C_I2C_PORT, AT24C_I2C_ADDR, I2C_Direction_Receiver);
	while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
#endif

  while(usBytesToRead)
  {
		if(usBytesToRead == 1)
		{
      I2C_AcknowledgeConfig(AT24C_I2C_PORT, DISABLE);	//* 最后一位后要关闭应答的
      I2C_GenerateSTOP(AT24C_I2C_PORT, ENABLE);			  //* 发送停止位
		}
	    
		while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_BYTE_RECEIVED));
    
    *pubReadBuf = I2C_ReceiveData(AT24C_I2C_PORT);    
    pubReadBuf++;
    usBytesToRead--;
  }
  
	//* 再次允许应答模式
	I2C_AcknowledgeConfig(AT24C_I2C_PORT, ENABLE); 
}

void E2WriteByte(UCHAR ubAddr, UCHAR ubValue)
{
  //* 起始位
  I2C_GenerateSTART(AT24C_I2C_PORT, ENABLE); 
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_MODE_SELECT)); 
  
#ifdef AT24C01
  I2C_Send7bitAddress(AT24C_I2C_PORT, ubAddr << 1, I2C_Direction_Transmitter);
 	while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
#else
  //* 发送器件地址(写)
  I2C_Send7bitAddress(AT24C_I2C_PORT, AT24C_I2C_ADDR, I2C_Direction_Transmitter);
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  
  //*发送地址
  I2C_SendData(AT24C_I2C_PORT, ubAddr); 
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
#endif  
  
  //* 写一个字节
  I2C_SendData(AT24C_I2C_PORT, ubValue); 
  while(!I2C_CheckEvent(AT24C_I2C_PORT, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  
  //* 停止位
  I2C_GenerateSTOP(AT24C_I2C_PORT, ENABLE);
  I2CAckPolling();

	I2CDelay(1000); 
}

void E2Write(UCHAR ubAddr, UCHAR *pubData, USHORT usDataBytes, CHAR bIsCriticalProtect)
{
  OS_CPU_SR cpu_sr = 0;  
  
  while(usDataBytes--)
  {
    if(bIsCriticalProtect)
      OS_ENTER_CRITICAL();  
    
    E2WriteByte(ubAddr++, *pubData++); 
    
    if(bIsCriticalProtect)
      OS_EXIT_CRITICAL(); 
  }
}

BOOL E2EthCfgWriteIp(PST_ETHCFG_IP pstEthCfg)
{
  pstEthCfg->usCRC = crc16((const uint8_t *)pstEthCfg, offsetof(ST_ETHCFG_IP, usCRC), 0xFFFF); 
  E2Write(0, (UCHAR *)pstEthCfg, sizeof(ST_ETHCFG_IP), TRUE); 
  
  OS_CPU_SR cpu_sr = 0; 
  ST_ETHCFG_IP stEthCfg; 
  OS_ENTER_CRITICAL();  
  E2Read(0, (UCHAR *)&stEthCfg, sizeof(ST_ETHCFG_IP)); 
  OS_EXIT_CRITICAL(); 
  
  return (BOOL)(pstEthCfg->usCRC == stEthCfg.usCRC); 
}

BOOL E2EthCfgReadIp(PST_ETHCFG_IP pstEthCfg)
{
  OS_CPU_SR cpu_sr = 0; 
  OS_ENTER_CRITICAL();  
  E2Read(0, (UCHAR *)pstEthCfg, sizeof(ST_ETHCFG_IP)); 
  OS_EXIT_CRITICAL(); 
  
  USHORT usCRC = crc16((const UCHAR *)pstEthCfg, offsetof(ST_ETHCFG_IP, usCRC), 0xFFFF); 
  return (BOOL)(usCRC == pstEthCfg->usCRC); 
}

BOOL E2EthCfgUpdateIp(UCHAR *pubData, CHAR bDataBytes, CHAR bOffset)
{
  ST_ETHCFG_IP stEthCfg; 
  if(E2EthCfgReadIp(&stEthCfg))
  {
    memcpy(((UCHAR *)&stEthCfg) + bOffset, pubData, bDataBytes);   
    return E2EthCfgWriteIp(&stEthCfg); 
  }  
  
  return FALSE; 
}

BOOL E2EthCfgWriteRouteEntry(PST_ETHCFG_ROUTE_ENTRY pstEntry)
{
  ST_ETHCFG_ROUTE_ENTRY stEntry; 
  OS_CPU_SR cpu_sr = 0;  
  USHORT usCRC; 
  
  //* 先查找空闲存储位置
  CHAR i; 
  UCHAR ubAddr = sizeof(ST_ETHCFG_IP); 
  for(i=0; i<ROUTE_ITEM_NUM; i++)
  {        
    //* 先读取当前存储位置的数据，看看是否是空闲位置
    OS_ENTER_CRITICAL(); 
    E2Read(ubAddr, (UCHAR *)&stEntry, sizeof(ST_ETHCFG_ROUTE_ENTRY));     
    OS_EXIT_CRITICAL(); 
    
    //* 计算CRC，如果CRC不匹配或者网关清零则意味着当前位置属于空闲位置，可以插入当前新增加的路由条目
    usCRC = crc16((const UCHAR *)&stEntry, offsetof(ST_ETHCFG_ROUTE_ENTRY, usCRC), 0xFFFF); 
    if((usCRC != stEntry.usCRC) || !stEntry.unGateway)
      break; 
    
    //* 读取地址更新为下一个条目存储单元
    ubAddr += sizeof(ST_ETHCFG_ROUTE_ENTRY); 
  }
  
  //* 存在空闲位置则添加路由条目
  if(ubAddr < sizeof(ST_ETHCFG_IP) + sizeof(ST_ETHCFG_ROUTE_ENTRY) * ROUTE_ITEM_NUM)
  {
    //* 计算CRC并写入数据
    pstEntry->usCRC = crc16((const UCHAR *)pstEntry, offsetof(ST_ETHCFG_ROUTE_ENTRY, usCRC), 0xFFFF);   
    E2Write(ubAddr, (UCHAR *)pstEntry, sizeof(ST_ETHCFG_ROUTE_ENTRY), TRUE); 
    
    //* 再次读出以验证刚才的写入是否成功
    OS_ENTER_CRITICAL();  
    E2Read(ubAddr, (UCHAR *)&stEntry, sizeof(ST_ETHCFG_ROUTE_ENTRY));  
    OS_EXIT_CRITICAL();  
    usCRC = crc16((const UCHAR *)&stEntry, offsetof(ST_ETHCFG_ROUTE_ENTRY, usCRC), 0xFFFF); 
    
    //* 判断写入成功的条件：1、读取出的数据通过CRC校验；2、CRC与原始数据CRC一致
    return (BOOL)(usCRC == stEntry.usCRC && usCRC == pstEntry->usCRC); 
  }
  
  return FALSE; 
}

BOOL E2EthCfgReadRouteEntry(PST_ETHCFG_ROUTE_ENTRY pstEntry, CHAR bEntryIdx)
{  
  OS_CPU_SR cpu_sr = 0;  
  USHORT usCRC;   
  UCHAR ubAddr = sizeof(ST_ETHCFG_IP) + sizeof(ST_ETHCFG_ROUTE_ENTRY) * bEntryIdx; 
  
  //* 先读取当前存储位置的数据，看看是否是空闲位置
  OS_ENTER_CRITICAL(); 
  E2Read(ubAddr, (UCHAR *)pstEntry, sizeof(ST_ETHCFG_ROUTE_ENTRY));     
  OS_EXIT_CRITICAL();  
  
  usCRC = crc16((const UCHAR *)pstEntry, offsetof(ST_ETHCFG_ROUTE_ENTRY, usCRC), 0xFFFF); 
  return (BOOL)((usCRC == pstEntry->usCRC) && pstEntry->unGateway); 
}

BOOL E2EthCfgDelRouteEntry(CHAR bEntryIdx)
{  
  //* 将网关置为0
  UCHAR ubAddr = sizeof(ST_ETHCFG_IP) + sizeof(ST_ETHCFG_ROUTE_ENTRY) * bEntryIdx + offsetof(ST_ETHCFG_ROUTE_ENTRY, unGateway); 
  UINT unGateway = 0; 
  E2Write(ubAddr, (UCHAR *)&unGateway, sizeof(unGateway), TRUE); 
  
  //* 读取更新后的网关
  OS_CPU_SR cpu_sr = 0; 
  OS_ENTER_CRITICAL();  
  E2Read(ubAddr, (UCHAR *)&unGateway, sizeof(unGateway));     
  OS_EXIT_CRITICAL();  
  
  //* 更新后的网关值为0则意味着删除成功
  return (BOOL)(!unGateway); 
}

void E2EthCfgRouteTblLoad(PST_NETIF pstNetif)
{
  ST_ETHCFG_ROUTE_ENTRY stEntry; 
  
  CHAR i; 
  for(i=0; i<ROUTE_ITEM_NUM; i++)
  {
    if(E2EthCfgReadRouteEntry(&stEntry, i))
      route_add(pstNetif, stEntry.unDestination, stEntry.unGateway, stEntry.unGenmask, NULL); 
  }  
}
#endif //* #if NETTOOLS_TELNETSRV
